package com.cheryjb.examples.gwt.clock.client;

import com.google.gwt.canvas.dom.client.Context2d;

/**
 * This is the super class for all Canvas Drawable objects.</br> It allows
 * positionning the object, moving it and rotating it around a Rotation Origin
 * point</br></br>
 * 
 * This class is abstract, all its child must define drawShapes method.
 * 
 * @author Jean-Baptiste Chery
 * 
 */
public abstract class ADrawableObject {

	/**
	 * x,y coordinates of the object
	 */
	private Vector position;

	/**
	 * When rotationDeg > 0, rotation is done around this point
	 */
	private final Vector rotationOrigin;

	/**
	 * angle of rotation in degree
	 */
	private double rotationDeg;

	/**
	 * Initiate the position. RotationOrigin is 0,0
	 * 
	 * @param position
	 *            the coordinates x,y of the object
	 */
	public ADrawableObject(final Vector position) {
		this(position, new Vector());
	}

	/**
	 * Initiate the position and the RotationOrigin
	 * 
	 * @param position
	 *            the coordinates x,y of the object
	 * @param rotationOrigin
	 *            When rotationDeg > 0, rotation is done around this point
	 */
	public ADrawableObject(final Vector position, final Vector rotationOrigin) {
		this.position = new Vector(position);
		this.rotationOrigin = rotationOrigin;
		rotationDeg = 0;
	}

	/**
	 * method that translate the object to the object position, and rotate it
	 * around the rotation origin
	 * 
	 * @param context
	 *            Canvas context
	 */
	public void draw(final Context2d context) {
		// context is save before transformation
		context.save();

		// transformations done on the context, not the object!
		context.translate(position.getX(), position.getY());
		rotate(context);

		// draw the object
		drawShapes(context);

		// restore the context as it was before transformation, to avoid
		// conflicts with other objects drawing.
		context.restore();
	}

	/**
	 * Abstract method defined by children.</br> It's used to draw the object
	 * (shapes, images etc...)
	 * 
	 * @param context
	 *            Canvas context
	 */
	public abstract void drawShapes(Context2d context);

	/**
	 * rotate the object of rotationDeg degrees around RotationOrigin point
	 * 
	 * @param context
	 *            Canvas context
	 */
	private void rotate(final Context2d context) {
		// translate to the rotation origin
		context.translate(rotationOrigin.getX(), rotationOrigin.getY());
		// rotate the image's top left corner
		context.rotate((rotationDeg * Math.PI) / 180d);
		// translate the image back to its position
		context.translate(-rotationOrigin.getX(), -rotationOrigin.getY());
	}

	// Getters and Setters

	public Vector getPosition() {
		return position;
	}

	public double getRotationDeg() {
		return rotationDeg;
	}

	public void setPosition(final Vector position) {
		this.position = position;
	}

	public void setRotationDeg(final double rotationDeg) {
		this.rotationDeg = rotationDeg;
	}

}
